package Infix2RPM.processor.infixElement;

import Infix2RPM.processor.Exception.BasicOperandException;
import Infix2RPM.processor.Exception.BasicOperatorException;
import Infix2RPM.processor.Exception.LogicException;
import Infix2RPM.processor.Stack.BasicOperand;

public class FloatOperand implements BasicOperand {
	private Float value = null;

	public FloatOperand(Float value) {
		this.value = value;
	}

	public FloatOperand add(BasicOperand operand) throws BasicOperandException {
		if (!(operand.getValue() instanceof Float)) {
			toss("Operand to add is not a Float");
		}
		return new FloatOperand(this.value += (Float) operand.getValue());
	}

	public FloatOperand subtract(BasicOperand operand)
			throws BasicOperandException {
		if (!(operand.getValue() instanceof Float)) {
			toss("Operand to subtract is not a Float");
		}
		return new FloatOperand(this.value -= (Float) operand.getValue());
	}

	public FloatOperand divide(BasicOperand operand)
			throws BasicOperandException {
		if (!(operand.getValue() instanceof Float)) {
			toss("Operand to divide is not a Float");
		}
		return new FloatOperand(this.value /= (Float) operand.getValue());
	}

	public FloatOperand multiply(BasicOperand operand)
			throws BasicOperandException {
		if (!(operand.getValue() instanceof Float)) {
			toss("Operand to multiply is not a Float");
		}
		return new FloatOperand(this.value *= (Float) operand.getValue());
	}

	public FloatOperand power(BasicOperand operand)
			throws BasicOperandException {
		if (!(operand.getValue() instanceof Float)) {
			toss("Operand to power is not an Float");
		}
		return new FloatOperand((float) Math.pow(this.value.doubleValue(),
				((Double) operand.getValue()).doubleValue()));
	}

	public FloatOperand mod(BasicOperand operand) throws BasicOperandException {
		if (!(operand.getValue() instanceof Float)) {
			toss("Operand to divide is not a Float");
		}
		return new FloatOperand(this.value.floatValue()
				% ((Float) operand.getValue()).floatValue());
	}

	public FloatOperand concat(BasicOperand operand)
			throws BasicOperatorException {
		throw new BasicOperatorException(
				"Concatentation of Float is unsupported", this.className());
	}

	public BooleanOperand equal(BasicOperand operand) throws LogicException {
		if (!(operand.getValue() instanceof Float)) {
			toss("Operand to == is not a Float");
		}
		return new BooleanOperand(this.value.floatValue() == ((Float) operand.getValue())
				.floatValue());
	}

	public BooleanOperand lessThan(BasicOperand operand)
			throws BasicOperandException {
		if (!(operand.getValue() instanceof Float)) {
			toss("Operand to < is not a Float");
		}
		return new BooleanOperand(
				this.value.floatValue() < ((Float) operand.getValue())
						.floatValue());
	}

	public BooleanOperand lessThanEqual(BasicOperand operand)
			throws BasicOperandException {
		if (!(operand.getValue() instanceof Float)) {
			toss("Operand to <= is not a Float");
		}
		return new BooleanOperand(
				this.value.floatValue() <= ((Float) operand.getValue())
						.floatValue());
	}

	public BooleanOperand greaterThan(BasicOperand operand)
			throws BasicOperandException {
		if (!(operand.getValue() instanceof Float)) {
			toss("Operand to > is not a Float");
		}
		return new BooleanOperand(this.value.floatValue() > ((Float) operand.getValue()).floatValue());
	}

	public BooleanOperand greaterThanEqual(BasicOperand operand)
			throws BasicOperandException {
		if (!(operand.getValue() instanceof Float)) {
			toss("Operand to >= is not a Float");
		}
		return new BooleanOperand(this.value.floatValue() >= ((Float) operand.getValue()).floatValue());
	}

	public BooleanOperand or(BasicOperand operand) throws LogicException {
		throw new BasicOperatorException(
				"Logical OR using Float is unsupported", this.className());
	}

	public BooleanOperand and(BasicOperand operand) throws LogicException {
		throw new BasicOperatorException(
				"Logical AND using Float is unsupported", this.className());
	}

	public boolean isNull() {
		return this.value == null;
	}

	public boolean isEmpty() {
		return this.value == null;
	}

	public Float getValue() {
		return this.value;
	}

	private void toss(String message) throws BasicOperandException {
		throw new BasicOperandException(message, this.getClass().getName());
	}

	public String getValueAsString() {
		return this.value.toString();
	}

	public boolean isEqual(String token) {
		return this.value.toString().equals(token);
	}

	private String className() {
		return this.getClass().getName();
	}
}
